package edu.gmu.projects.fireresponder.comm;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URISyntaxException;
import java.net.UnknownHostException;

import javax.crypto.Cipher;

import android.content.Context;
import android.util.Log;
import edu.gmu.projects.fireresponder.xml.alerts.Alert;
import edu.gmu.projects.fireresponder.xml.alerts.AlertFactory;

public class EmulatorCommunicator extends MessageCommunicator {

	public static final String HOST = "10.0.2.2";
	public static final int PORT = 8882;
	
	protected InetAddress hostAddr;
	private Socket server;
	private ObjectOutputStream outputStream;
	private ObjectInputStream inputStream;
		
	protected Context context;
	protected Cipher encCipher;
	protected Cipher decCipher;

	private boolean initialized = false;
	
	public EmulatorCommunicator(Context context) {
		this.context = context;
		init();
	}
	
	private void init() {
		try {
			server = new Socket(HOST, PORT);
			outputStream = new ObjectOutputStream(server.getOutputStream());
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		initialized = true;
		try {
			startListener();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
	}
	
	public boolean isInitialized() {
		return initialized;
	}
	
	protected void finalize() throws Throwable {
		server.close();
        super.finalize();
	}


	/* (non-Javadoc)
	 * @see com.lmco.atl.swtp.network.Broadcast#send(com.lmco.atl.swtp.network.String)
	 */
	public boolean send(String msg) {
		try {
			outputStream.writeObject(msg);				
		} catch (NullPointerException e) {
			Log.d("-----udp", "NullPointerException sending UDP String: " + e.getMessage());
			return false;
		} catch (IOException e) {
			Log.d("-----udp", "IOException sending UDP String: " + e.getMessage());
			return false;
		}
		return true;
	}

	protected void startListener() throws URISyntaxException {

		Thread thread = new Thread(new SocketListener(this), "Socket Listener");
		thread.start();
		Thread.yield();
		
		String task = new String("android 1");
		send(task);
		Log.i("-----Sent", task);
		task = new String("android 2");
		send(task);
		Log.i("-----Sent", task);
		task = new String("android 3");
		send(task);
		Log.i("-----Sent", task);
		task = new String("android 4");
		send(task);
		Log.i("-----Sent", task);
	}
	
	/* (non-Javadoc)
	 * @see com.lmco.atl.swtp.network.Broadcast#receive()
	 */
	public String receive() {
		String task = null;

		try {
			task = (String) inputStream.readObject();
		} catch (NullPointerException e) {
			Log.d("-----udp", "NullPointerException receiving UDP String: " + e.getMessage());
		} catch (IOException e) {
			//Log.d("-----udp", "IOException receiving UDP String: " + e.getMessage());
		} catch (ClassNotFoundException e) {
			Log.d("-----udp", "ClassNotFoundException receiving UDP String: " + e.getMessage());
		}
		
		return task;
	}
	
	protected class SocketListener implements Runnable {
		
		MessageCommunicator bc;
		public SocketListener(MessageCommunicator bc) {
			this.bc = bc;
		}
		
		public void run() {
			try {
				inputStream = new ObjectInputStream(server.getInputStream());
			} catch (StreamCorruptedException e) {
				e.printStackTrace();
				Log.e("-----Received", "StreamCorruptedException: " + e.getMessage());
			} catch (IOException e) {
				e.printStackTrace();
				Log.e("-----Received", "IOException: " + e.getMessage());
			}

			while (true) {
				String task = bc.receive();
				if(task == null) {
					continue;
				}
				task = task.trim();
				
				Log.i("------Received", task);

				if (task != null) {
					Alert alert = AlertFactory.createAlertFromMessage(task);

					if (alert != null) {
						for (MessageListener listener : listeners)
						{
							listener.receivedAlertMessage(alert);
						}
					}
				}
			}
		}
	}
}
